package com.example.luyao.myapplication;

import android.app.AlertDialog;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

import com.junkchen.blelib.BleService;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import me.jessyan.autosize.internal.CustomAdapt;

public class MainActivity extends AppCompatActivity implements BleService.OnConnectionStateChangeListener,
        BleService.OnServicesDiscoveredListener, BleService.OnDataAvailableListener, CustomAdapt {
    private final static String TAG = Constants.LOG_PREFIX + MainActivity.class.getCanonicalName();
    private Button button_start;
    private Button button_line;
    private Button button_m;
    private Button button_home;
    private Button button_file;
    private ListView bluetooth_list;
    private QuadBezierView coffee_view;

    AlertDialog lineChooseDialog;

    private String bluetooth_name;
    private String bluetooth_mac;

    private BleService mBleService;
    private boolean mIsBind;
    private ServiceConnection serviceConnection;
    private String serviceUUID = "0000FFE0-0000-1000-8000-00805F9B34FB";
    private String characteristicUUID = "0000FFE1-0000-1000-8000-00805F9B34FB";
    private byte[] bluetooth_input;
    private boolean stopBlueToothThread = false;
    private boolean blueToothConnected = false;
    private static BlueToothThread blueToothThread = null;
    private Lock inputLock = new ReentrantLock();

    protected void toast(final String msg) {
        runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
                }
            });
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
            //actionBar.setHomeButtonEnabled(true);
            //actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setTitle("Coffee");
        }
        
        coffee_view = findViewById(R.id.coffee_view);
        button_start = findViewById(R.id.button_start);
        button_line = findViewById(R.id.button_line);
        button_line.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //button_start.setEnabled(false);
                //addPointClick();
                chooseLines();
            }
        });

        button_m = findViewById(R.id.button_m);
        button_home = findViewById(R.id.button_home);
        button_home.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        button_file = findViewById(R.id.button_file);

        bluetooth_name = getIntent().getStringExtra("name");
        bluetooth_mac = getIntent().getStringExtra("mac");
        Log.e(TAG, "oncreate " + bluetooth_name + " " + bluetooth_mac);

        /*init_bluetooth();
        blueToothThread = new BlueToothThread();
        blueToothThread.start();*/
    }

    protected void chooseLines(){
        List<Map<String, String>> data = new ArrayList<>();
        List<String> names = new ArrayList<>();
        names.add("淺烘培 L");
        names.add("肉桂烘培 ML");
        names.add("中度烘培 M");
        names.add("城市烘培 MD");
        names.add("深城市烘培 D");
        names.add("自定义");
        for(int i = 0; i < 6; i++){
            Map map = new HashMap();
            map.put("name", names.get(i));
            data.add(map);
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        lineChooseDialog = builder.create();
        View dialogView = View.inflate(this, R.layout.activity_lines, null);
        lineChooseDialog.setView(dialogView);
        lineChooseDialog.show();

        CustomAdapter customAdapter = new CustomAdapter(
                this, data, this, 0, 1, lineChooseDialog, coffee_view);
        ListView listView = dialogView.findViewById(R.id.lines_list);
        listView.setAdapter(customAdapter);
    }

    private void init_bluetooth() {
        serviceConnection = new ServiceConnection() {

            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mBleService = ((BleService.LocalBinder) service).getService();
                //if (mBleService != null) mHandler.sendEmptyMessage(SERVICE_BIND);
                if (mBleService.initialize()) {
                    if (mBleService.enableBluetooth(true)) {
                        mBleService.setOnServicesDiscoveredListener(MainActivity.this);
                        mBleService.setOnConnectListener(MainActivity.this);
                        mBleService.setOnDataAvailableListener(MainActivity.this);
                        mBleService.connect(bluetooth_mac);
                        Log.e(TAG, "mBleService was Connected");
                    }
                } else {
                    toast("蓝牙服务启动失败");
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                mBleService = null;
                mIsBind = false;
            }
        };
        doBindService();
    }

    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState){
        if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            Log.e(TAG, "onConnectionStateChange Ble连接已断开");
        } else if (newState == BluetoothProfile.STATE_CONNECTING) {
            Log.e(TAG, "onConnectionStateChange Ble正在连接");
        } else if (newState == BluetoothProfile.STATE_CONNECTED) {
            Log.e(TAG, "onConnectionStateChange Ble已连接");
        } else if (newState == BluetoothProfile.STATE_DISCONNECTING) {
            Log.e(TAG, "onConnectionStateChange Ble正在断开连接");
        } else {
            Log.e(TAG, "onConnectionStateChange unknow status");
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        List<BluetoothGattService> services = gatt.getServices();
        if(services != null) {
            for(int i = 0; i < services.size(); i++){
                Log.e(TAG, "service " + i + " " + services.get(i).getUuid());
                //characteristicUUID = services.get(i).getCharacteristic();
            }
            blueToothConnected = true;
            //mBleService.setCharacteristicNotification(MainActivity.this);
        }
        Log.e(TAG, gatt.toString());
    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,
                                     BluetoothGattCharacteristic characteristic, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            inputLock.lock();
            bluetooth_input = characteristic.getValue();
            if(bluetooth_input.length == 0) {
                bluetooth_input = null;
            } else {
            }
            inputLock.unlock();
            if(bluetooth_input != null) {
                Log.e(TAG, "onCharacteristicRead get byte length: " + bluetooth_input.length);
                if(bluetooth_input.length >= 0) {
                    Log.e(TAG, "onCharacteristicRead get byte: " + bluetooth_input[0]);
                }
            } else {
                //Log.e(TAG, "onCharacteristicRead get byte length: " + 0);
            }
        }
    }
    
    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,
                                        BluetoothGattCharacteristic characteristic) {
        Log.e(TAG, "onCharacteristicChanged");
    }

    @Override
    public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status){
        Log.e(TAG, "onDescriptorRead");
    }

    private void readData(){
        mBleService.readCharacteristic(serviceUUID, characteristicUUID);
    }

    private void sendData(byte[] data){
        mBleService.writeCharacteristic(serviceUUID, characteristicUUID, data);
    }
    
    private void doBindService() {
        Intent serviceIntent = new Intent(this, BleService.class);
        bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    private void doUnBindService() {
        if (mIsBind) {
            unbindService(serviceConnection);
            mBleService = null;
            mIsBind = false;
        }
    }
    
    public void addPointClick() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        final AlertDialog dialog = builder.create();
        View dialogView = View.inflate(this, R.layout.point_add, null);
        dialog.setView(dialogView);
        dialog.show();
        EditText text_time = dialogView.findViewById(R.id.text_time);
        EditText text_temperature = dialogView.findViewById(R.id.text_temperature);
        Button confirm_button = dialogView.findViewById(R.id.confirm_button);
        Button cancel_button = dialogView.findViewById(R.id.cancel_button);
        confirm_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    final int time = Integer.valueOf(text_time.getText().toString());
                    final int temperature = Integer.valueOf(
                            text_temperature.getText().toString());
                    Log.e(TAG, time + " " + temperature);
                    int x_max = 30;
                    int y_max = 300;
                    if (time < 0 || time > x_max || temperature < 0 || temperature > y_max) {
                        toast("时间和温度超过允许范围!");
                        return;
                    }
                    coffee_view.addPoint(time, temperature);
                } catch (NumberFormatException e){
                    e.printStackTrace();
                    toast("时间和温度格式错误!");
                }
                dialog.dismiss();

            }
        });
        cancel_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.e(TAG, "lifecycle: onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.e(TAG, "lifecycle: onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.e(TAG, "lifecycle: onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.e(TAG, "lifecycle: onStop");
    }

    @Override
    protected void onDestroy() {
        Log.e(TAG, "lifecycle: onDestroy");
        stopBlueToothThread = true;
        if (blueToothThread != null) {
            try {
                blueToothThread.join();
                blueToothThread = null;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        mBleService.disconnect();
        doUnBindService();
        super.onDestroy();
    }

    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
            //return true;
        }
        return super.onKeyUp(keyCode, event);
    }

    public class BlueToothThread extends Thread {
        public BlueToothThread() {
            super();
        }

        private byte get_sum_check(byte[] d){
            byte b = 0x00;
            for(int i = 0; i < d.length - 1; i++){
                b &= d[i];
            }
            return b;
        }

        private void write_header(char type, char cmd,  char len, char index){
            try {
                byte[] b = new byte[5];
                b[0] =  (byte)type;
                b[1] =  (byte)cmd;
                b[2] =  (byte)len;
                b[3] =  (byte)index;
                b[4] =  get_sum_check(b);
                sendData(b);
            }catch (Exception e) {
                e.printStackTrace();
            }
        }

        private void query_device_status(){
            write_header((char)0x21, (char)0xC0, (char)0x05, (char)0x0);
            //write_header((char)0xA5, (char)0x11, (char)0x05, (char)0x0);
        }

        @Override
        public void run() {
            while(!blueToothConnected){
                Log.e(TAG, "blueTooth not Connected");
                if(stopBlueToothThread) return;
                Utils.sleep_millis(500);
            }
            query_device_status();
            Utils.sleep_millis(1000);
            while(!stopBlueToothThread) {
                try {
                    //Log.e(TAG, "wait server data");
                    readData();
                    byte[] data = null;
                    if(true){
                        inputLock.lock();
                        if(bluetooth_input != null) {
                            data = bluetooth_input;
                            bluetooth_input = null;
                            inputLock.unlock();
                        } else {
                            inputLock.unlock();
                        }
                        if(data == null) {
                            Utils.sleep_millis(10);
                            continue;
                        }
                    }
                    ByteBuffer wrapped = ByteBuffer.wrap(data);
                    if(data.length >= 5) {
                        int type = wrapped.getChar(0);
                        Log.e(TAG, "got header type " + data.length);
                        Log.e(TAG, "got header type " + data.length + " " + data[0]);
                        int cmd = wrapped.getChar(1);
                        int len = wrapped.getChar(2);
                        int index = wrapped.getChar(3);
                        int index_1 = wrapped.getChar(4);

                        Log.e(TAG, "got header type " + type + " cmd " + cmd +
                                " len " + len + " index " + index + " index_1 " + index_1);
                        if (type != 0xAA) {
                            continue;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            Log.e(TAG, "BlueToothThread quit.");
        }
    }

    @Override
    public boolean isBaseOnWidth() {
        return false;
    }

    @Override
    public float getSizeInDp() {
        return 667;
    }
}
